/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cflp;

import shortestPath.*;

/**
 *
 * @author Administrador
 */
public class FlujoMaximo {

    private Network net;
    private double[][] spc, spt;

    public static void main(String[] args) {
        FlujoMaximo fm=new FlujoMaximo();
        int[] sol = {0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0};
        int[][] cant=fm.servedNodes(sol);
         for(int i=0;i<cant.length;++i){
             for(int j=0;j<cant[i].length;++j){
                 if(cant[i][j]>0){System.out.println((i+1)+"-"+(j+1)+":"+cant[i][j]+"\t");}
             }
         }
    }

    public FlujoMaximo() {
        String nombre = "problemas/N50L2U2K25F10.txt";
        net = new Network(nombre);
        int arcos = net.getArcsNumber();
        spc = (new ConstructEdges(net.getCosts(), false, arcos)).getSP();
        spt = (new ConstructEdges(net.getDistances(), false, arcos)).getSP();
    }

    public int[][] servedNodes(int[] wn) {

        int[][] servn = new int[net.getNodesNumber()][net.getNodesNumber()];
        for (int i = 0; i < servn.length; ++i) {
            for (int j = 0; j < servn[i].length; ++j) {
                servn[i][j] = 0;
            }
        }
        //se obtiene la demanda de los nodos
        int[] demand = new int[net.getNodesNumber()];
        System.arraycopy(net.getDemand(), 0, demand, 0, net.getNodesNumber());
        int[] asigCap = new int[net.getNodesNumber()];
        System.arraycopy(net.getWarehouseCapacity(), 0, asigCap, 0, net.getNodesNumber());

        int totalCap = 0;
        int wnumber = 0;
        //se asignan los nodos que se sirven asi mismo
        for (int i = 0; i < wn.length; ++i) {
            if (wn[i] == 1) {
                totalCap = totalCap + asigCap[i];
                wnumber = wnumber + 1;
                servn[i][i] = demand[i];
                asigCap[i] = asigCap[i] - demand[i];
            }
            if (wn[i] == 0) {
                asigCap[i] = 0;
            }
        }

        //se construye la red para asignar el problema

        int dest = (totalCap == net.getDemTotal()) ? (net.getNodesNumber() - wnumber) : (net.getNodesNumber() - wnumber + 1);

        int[][] e = new int[wnumber + wnumber * dest + dest][5];
        int ne = 0;
        //se cosntruyen los ejes
        for (int w = 0; w < wn.length; ++w) {
            if (wn[w] == 1) {
                e[ne][0] = 0;
                e[ne][1] = w + 1;
                e[ne][2] = asigCap[w];
                e[ne][3] = 0;
                e[ne][4] = 0;
                ne = ne + 1;
                for (int i = 0; i < wn.length; ++i) {
                    if (wn[i] == 0) {
                        e[ne][0] = w + 1;
                        e[ne][1] = i + 1;
                        e[ne][2] = totalCap;
                        e[ne][3] = (int) spc[w][i];
                        e[ne][4] = 0;
                        ne = ne + 1;
                    }
                }
            } else {
                e[ne][0] = w + 1;
                e[ne][1] = wnumber + dest + 1;
                e[ne][2] = demand[w];
                e[ne][3] = 0;
                e[ne][4] = 0;
                ne = ne + 1;
            }

        }

        if (dest > net.getNodesNumber() - wnumber) {
            e[ne][0] = dest + wnumber;
            e[ne][1] = wnumber + dest + 1;
            e[ne][2] = totalCap - net.getDemTotal();
            e[ne][3] = 0;
            e[ne][4] = 0;
            ne = ne + 1;
            for (int i = 0; i < wn.length; ++i) {
                if (wn[i] == 1) {
                    e[ne][0] = i + 1;
                    e[ne][1] = dest + wnumber;
                    e[ne][2] = totalCap;
                    e[ne][3] = 0;
                    e[ne][4] = 0;
                    ne = ne + 1;
                }
            }
        }

        //for(int i=0;i<e.length;++i)System.out.println(e[i][0]+"\t"+e[i][1]+"\t"+e[i][2]+"\t"+e[i][3]+"\t"+e[i][4]);
        int nodes=wnumber + dest + 1;
        int[][] sol=new int[nodes+1][nodes+1];
        networkFlow.Edge[] edges=new networkFlow.Edge[e.length];

        for(int i=0;i<e.length;++i){
            edges[i]=new networkFlow.Edge(e[i][0],e[i][1],e[i][2],e[i][3],e[i][4]);
        }

        networkFlow.Network n=new networkFlow.Network(nodes+1);
        for(int i=0; i<edges.length;++i){
            n.insert(edges[i]);
        }

        networkFlow.NetworkMaxFlow M = new networkFlow.NetworkMaxFlow(n, 0, nodes);

        for(int i=0; i<n.getV();++i){
            networkFlow.AdjList A = n.getAdjList(i);
            for(networkFlow.Edge ed=A.beg();!A.end(); ed=A.nxt()){
                int origin=ed.getV();
                int ndest=ed.getW();
                int flow=ed.getPflow();
                sol[origin][ndest]=flow;
            }

        }

        System.out.println(networkFlow.NetworkUtilities.flow(n,nodes));
        System.out.println(networkFlow.NetworkUtilities.flow(n,0));
        System.out.println(networkFlow.NetworkUtilities.flowcheck(n, 0, nodes));

        for(int i=0;i<net.getNodesNumber();i++){
            for(int j=0;j<net.getNodesNumber();j++){
                if(sol[i+1][j+1]>0){
                    servn[i][j]=sol[i+1][j+1];
                }

            }
        }


        return servn;

    }
}
